home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / hppcmode.arc / KBIBM.ASM next >
Assembly Source File  |  1984-10-08  |  50KB  |  1,321 lines

  1.   page 60,132
  2. ;****************************************************************************
  3. ;****************************************************************************
  4. ;
  5. ;   KBIBM.ASM -
  6. ;    IBM STYLE KEYBOARD DRIVER FOR THE HP150
  7. ;
  8. ;            Kirk L. Bentson
  9. ;
  10. ;            Hewlett-Packard
  11. ;        Personal Office COmputer Division
  12. ;            March 1984
  13. ;
  14. ; Modification History -
  15. ;
  16. ;    Code taken over Aug, 1984 by Frank Heartney. All separate
  17. ;    Include files combined into a single source file, code and
  18. ;    data included in a segment called 'CODE'. Calling sequences
  19. ;    changed to be used with PC.ASM, a PC emulator on the HP150.
  20. ;
  21. ;
  22. ; these routines take over keyboard handling at the hardware level.
  23. ; When these routines are active, the HP150 firmware is getting
  24. ; no reports from the keyboard, and the keyboard returns it's 
  25. ; information in IBM PC style format.
  26. ;
  27. ;****************************************************************************
  28. ;****************************************************************************
  29.  
  30. ;****************************************************************************
  31. ;   Keyboard driver constant equates.
  32. ;****************************************************************************
  33. TRUE    equ    001H        ;Non-zero boolean true value
  34. FALSE    equ    000H        ;Zero boolean false value
  35. SUCCESS equ    001H        ;Non-zero boolean success value
  36. FAIL    equ    000H        ;Zero boolean fail value
  37.  
  38. KBSW_TYPE   equ    016H     ;Keyboard I/O interrupt number
  39. BREAK_TYPE  equ    01BH     ;User break routine interrupt
  40. KBHW_TYPE   equ    043H     ;8041 interrupt number
  41.  
  42. KB_STAT     equ    019H     ;8041 status port  - read
  43. KB_CMND     equ    019H     ;8041 command port - write
  44. KB_DATA     equ    018H     ;8041 data port - read
  45. IC_CMND     equ    010H     ;8259 command port - write
  46.  
  47. ACK_CMND    equ    010H     ;8041 Acknowledge interrupt command
  48. TONE_0_CMND equ    030H     ;8041 Generate tone 030H command
  49. EOI_CMND    equ    020H     ;8259 End Of Interrupt command
  50.  
  51. ;8041 status register bit masks
  52. ;Note - Bits 4,5,6,7 have different meanings depending on last 8041 function
  53. ;    Only keyboard and touchscreen masks have been defined here
  54. OBF_MASK    equ    00000001B        ;8041 status, OBF flag mask
  55. IBF_MASK    equ    00000010B        ;8041 status, IBF flag mask
  56. REL_MASK    equ    00110000B        ;8041 status, touch release mask
  57. ROW_MASK    equ    01000000B        ;8041 status, touch report row mask
  58. COL_MASK    equ    01010000B        ;8041 status, touch report col mask
  59. TS_MASK     equ    REL_MASK or ROW_MASK or COL_MASK
  60.  
  61. KEY_RELEASE equ    10000000B        ;8041 data, key released mask
  62.  
  63. ;****************************************************************************
  64. ;****************************************************************************
  65. ;
  66. ;  KBDRIVER.ASM -
  67. ;     KEYBOARD DRIVER INIT, RESET, AND 8041 COMMUNICATION ROUTINES
  68. ;
  69. ;
  70. ;  The routines in this module perform the functions needed to initialize
  71. ;  the keyboard driver at start-up and to reset the system state when
  72. ;  the driver is no longer needed.  All necessary routines are provided
  73. ;  for communicating with the 8041.
  74. ;      kb_init     - Initialize keyboard driver
  75. ;      kb_reset    - Reset system state
  76. ;      kb_cmnd_out - Send command to 8041
  77. ;****************************************************************************
  78. ;****************************************************************************
  79. seg_0    segment at 00000H
  80.     assume cs:nothing,ds:nothing,ss:nothing,es:nothing
  81.  
  82.     org    KBSW_TYPE*4
  83. kb_io_ptr   label  dword        ;Keyboard I/O interrupt vector
  84. kb_io_oset  label  word         ;    Offset
  85.     org    kb_io_oset+2
  86. kb_io_seg   label  word         ;    Segment
  87.  
  88.     org    BREAK_TYPE*4
  89. break_ptr   label  dword        ;User break routine interrupt
  90. break_oset  label  word         ;    Offset
  91.     org    break_oset+2
  92. break_seg   label  word         ;    Segment
  93.  
  94.     org    KBHW_TYPE*4
  95. kb_int_ptr  label  dword        ;8041 interrupt vector
  96. kb_int_oset label  word         ;    Offset
  97.     org    kb_int_oset+2
  98. kb_int_seg  label  word         ;    Segment
  99.  
  100. seg_0    ends
  101.     page
  102.  
  103. pccode  segment byte public 'CODE'
  104.     assume cs:pccode,ds:pccode
  105.  
  106. ;The keyboard driver is installed by setting all necessary interrupt vectors
  107. ;to point to the proper driver routines.  Before the interrupt vectors are
  108. ;changed they are saved so that they may be restored to remove the keyboard
  109. ;driver and return the system to its normal keyboard state.
  110. ;These save areas are set up to store the original interrupt vectors.
  111. kbsw_save   label  dword        ;Keyboard I/O vector save area
  112. kbsw_oset   dw     ?            ;    Offset
  113. kbsw_seg    dw     ?            ;    Segment
  114.  
  115.  
  116. ;****************************************************************************
  117. ;  KB_INIT - Initialize keyboard driver.
  118. ;      This routine installs and initializes the keyboard driver.  The
  119. ;      keyboard driver is installed by saving the necessary interrupt
  120. ;      vectors and replacing them with new vectors that point to
  121. ;      the keyboard driver's routines.
  122. ;
  123. ;      Registers in:
  124. ;        None.
  125. ;      Registers out:
  126. ;        None.
  127. ;      Registers preserved:
  128. ;        All.
  129. ;****************************************************************************
  130.     public kb_init
  131. kb_init proc    near            ;Initialize keyboard routines
  132.     push    ax            ;Save callers registers
  133.     push    ds
  134.     push    es
  135.     push    cs            ;data is in code segment.
  136.     pop    ds    
  137.     sub    ax,ax            ;Point es to segment 0
  138.     mov    es,ax
  139.  
  140.     cli                ;Disable external interrupts
  141.     mov    ax,es:kb_io_oset     ;Save current keyboard I/O vector
  142.     mov    kbsw_oset,ax
  143.     mov    ax,es:kb_io_seg
  144.     mov    kbsw_seg,ax
  145.     mov    ax,offset kb_io      ;Install new keyboard I/O vector
  146.     mov    es:kb_io_oset,ax
  147.     mov    es:kb_io_seg,cs
  148.     sti                ;Enable external interrupts
  149.  
  150.     pop    es            ;Restore callers registers
  151.     pop    ds
  152.     pop    ax
  153.     ret                ;Return to caller
  154. kb_init     endp
  155.     page
  156. ;****************************************************************************
  157. ;  KB_RESET - Remove keyboard driver and return system to normal keyboard.
  158. ;      This routine removes the keyboard driver by restoring the
  159. ;      necessary interrupt vectors with the values that were stored
  160. ;      when the driver was initialized.
  161. ;
  162. ;      Registers in:
  163. ;        None.
  164. ;      Registers out:
  165. ;        None.
  166. ;      Registers preserved:
  167. ;        All.
  168. ;****************************************************************************
  169.     public kb_reset
  170. kb_reset proc   near             ;Reset keyboard routines
  171.     push    ax            ;Save callers registers
  172.     push    ds
  173.     push    es
  174.     push    cs            ;data is in code segment.
  175.     pop    ds
  176.     sub    ax,ax            ;Point es to segment 0
  177.     mov    es,ax
  178.  
  179.     cli                ;Disable external interrupts
  180.     mov    ax,kbsw_oset        ;Restore keyboard I/O vector
  181.     mov    es:kb_io_oset,ax
  182.     mov    ax,kbsw_seg
  183.     mov    es:kb_io_seg,ax
  184.     sti                ;Enable external interrupts
  185.  
  186.     pop    es            ;Restore callers registers
  187.     pop    ds
  188.     pop    ax
  189.     ret                ;Return to caller
  190. kb_reset    endp
  191.     page
  192. ;****************************************************************************
  193. ;  KB_CMND_OUT - Send a command to the 8041
  194. ;      This routine checks to see if the 8041 is ready for a command.
  195. ;      If it is then the specified command byte is written to the 8041.
  196. ;      If the 8041 is busy then this routine waits for awhile to see if
  197. ;      it becomes ready.
  198. ;
  199. ;      Registers in:
  200. ;        AH   - Command byte to be sent to 8041
  201. ;      Registers out:
  202. ;        AX   - 00001H if the command was sent to the 8041
  203. ;          00000H - timeout, 8041 is busy
  204. ;      Registers preserved:
  205. ;        All except AX.
  206. ;****************************************************************************
  207. kb_cmnd_out proc   near
  208.     push    cx            ;Save callers cx
  209.     mov    cx,0FFFFH
  210. kb_cmnd_01  label  near
  211.     in    al,KB_STAT        ;Read 8041 status byte
  212.     test    al,IBF_MASK        ;If IBF=1 then loop for awhile to
  213.     jz    kb_cmnd_02        ;    see if it changes to 0
  214.     loop    kb_cmnd_01
  215.     mov    ax,FAIL          ;Timeout - set return value and
  216.     jmp    kb_cmnd_03        ;    return
  217. kb_cmnd_02  label  near
  218.     mov    al,ah            ;Write command to 8041
  219.     out    KB_CMND,al
  220.     mov    ax,SUCCESS        ;Set return value
  221. kb_cmnd_03  label  near
  222.     pop    cx            ;Restore callers cx
  223.     ret                ;    and return to caller
  224. kb_cmnd_out endp
  225.  
  226.  
  227. ;****************************************************************************
  228. ;****************************************************************************
  229. ;
  230. ;  KEYBOARD QUEUE HANDLING ROUTINES
  231. ;
  232. ;
  233. ;  Each routine in this module performs a function related to keyboard
  234. ;  queue management.  The keyboard queue is a fixed length FIFO queue
  235. ;  whose entries are two bytes (one word) in length.  The queue entries
  236. ;  are stored in a contiguous memory area the length of which is
  237. ;  determined by a constant equate.  The first word of the memory area is
  238. ;  referred to as the queue beginning and the last word is referred to as
  239. ;  the queue end.  The oldest entry placed in the queue is referred to as
  240. ;  the head entry and the latest queue entry is referred to as the tail
  241. ;  entry.  A keyboard queue pointer is a segment offset to an entry in
  242. ;  the queue.  Every keyboard pointer must point to an address within the
  243. ;  queue memory area at all times.
  244. ;      kb_inc_ptr    - Increment keyboard queue pointer by one entry
  245. ;      kb_is_q_empty - Returns ZF=1 if keyboard queue is empty
  246. ;      kb_is_q_full  - Returns ZF=1 if keyboard queue is full
  247. ;      kb_reset_q    - Resets keyboard queue to empty
  248. ;      kb_read_q    - If keyboard queue not empty
  249. ;             returns head queue entry
  250. ;      kb_write_q    - If keyboard queue not full
  251. ;             adds ax to queue tail
  252. ;****************************************************************************
  253. ;****************************************************************************
  254.         page
  255.  
  256. KB_QUEUE_LEN equ   051          ;Keyboard queue length in words
  257.  
  258. kb_queue    dw     KB_QUEUE_LEN dup(?)      ;Keyboard queue
  259. kb_q_end    label  word         ;    End of queue pointer
  260. kb_q_head   dw     offset kb_queue    ;    Keyboard queue head pointer
  261. kb_q_tail   dw     offset kb_queue    ;    Keyboard queue tail pointer
  262.  
  263. ;****************************************************************************
  264. ;  KB_INC_PTR - Increment keyboard queue pointer by one entry.
  265. ;      The keyboard queue pointer in bx is incremented by one word and
  266. ;      if it then points past the end of the queue the pointer is
  267. ;      wrapped around to the beginning of the queue.
  268. ;
  269. ;      Registers in:
  270. ;        BX   - Keyboard queue pointer
  271. ;      Registers out:
  272. ;        BX   - Incremented keyboard queue pointer
  273. ;      Registers preserved:
  274. ;        All except BX, FF
  275. ;****************************************************************************
  276. kb_inc_ptr  proc   near         ;Increment keyboard queue pointer
  277.     add    bx,2            ;Point to next queue entry
  278.     cmp    bx,offset kb_q_end    ;If at end of queue
  279.     jb    kb_inc_005        ;    then wrap around to beginning
  280.     mov    bx,offset kb_queue    ;    of queue
  281. kb_inc_005  label  near
  282.     ret                ;Return to caller
  283. kb_inc_ptr  endp
  284.  
  285. ;****************************************************************************
  286. ;  KB_IS_Q_EMPTY - Check if keyboard queue is empty.
  287. ;      This routine sets the zero flag (ZF) to reflect whether the
  288. ;      keyboard queue is empty or not.
  289. ;
  290. ;      Registers in:
  291. ;        None.
  292. ;      Registers out:
  293. ;        FF   - ZF=1 - Keyboard queue is empty
  294. ;          ZF=0 - Keyboard queue is not empty
  295. ;      Registers preserved:
  296. ;        All except FF
  297. ;****************************************************************************
  298.     public    kb_is_q_empty
  299. kb_is_q_empty proc near         ;Returns ZF=1 if keyboard queue
  300.     push    bx            ;    is empty
  301.     mov    bx,kb_q_tail
  302.     cmp    bx,kb_q_head        ;Set ZF to reflect queue status
  303.     pop    bx
  304.     ret                ;Return to caller
  305. kb_is_q_empty endp
  306.     page
  307. ;****************************************************************************
  308. ;  KB_IS_Q_FULL - Check if keyboard queue is full.
  309. ;      This routine sets the zero flag (ZF) to reflect whether the
  310. ;      keyboard queue is full or not.
  311. ;
  312. ;      Registers in:
  313. ;        None.
  314. ;      Registers out:
  315. ;        FF   - ZF=1 - Keyboard queue is full
  316. ;          ZF=0 - Keyboard queue is not full
  317. ;      Registers preserved:
  318. ;        All except FF
  319. ;****************************************************************************
  320. kb_is_q_full proc  near         ;Returns ZF=1 if keyboard queue
  321.     push    bx            ;    is full
  322.     mov    bx,kb_q_tail
  323.     call    kb_inc_ptr
  324.     cmp    bx,kb_q_head        ;Set ZF to reflect queue status
  325.     pop    bx
  326.     ret                ;Return to caller
  327. kb_is_q_full endp
  328.  
  329. ;****************************************************************************
  330. ;  KB_RESET_Q - Resets the keyboard queue to empty.
  331. ;      This routine simply sets the keyboard queue head and tail pointers
  332. ;      to the queue beginning thereby setting the queue to an empty state.
  333. ;
  334. ;      Registers in:
  335. ;        None.
  336. ;      Registers out:
  337. ;        None.
  338. ;      Registers preserved:
  339. ;        All except FF
  340. ;****************************************************************************
  341. kb_reset_q  proc   near         ;Resets keyboard queue to empty
  342.     push    bx
  343.     mov    bx,offset kb_queue
  344.     mov    kb_q_head,bx
  345.     mov    kb_q_tail,bx
  346.     pop    bx
  347.     ret                ;Return to caller
  348. kb_reset_q  endp
  349.     page
  350. ;****************************************************************************
  351. ;  KB_READ_Q - Read the head keyboard queue entry.
  352. ;      If the keyboard queue is not empty this routine reads the head
  353. ;      entry and removes it from the queue.
  354. ;
  355. ;      Registers in:
  356. ;        None.
  357. ;      Registers out:
  358. ;        FF   - ZF=0 - Operation successful
  359. ;             AX contains head keyboard queue entry
  360. ;          ZF=1 - Operation unsuccessful
  361. ;             Keyboard queue was empty
  362. ;      Registers preserved:
  363. ;        All except AX, FF
  364. ;****************************************************************************
  365. kb_read_q   proc   near         ;If keyboard queue not empty
  366.     push    bx            ;    returns ZF=0 and head queue
  367.     call    kb_is_q_empty        ;    element in AX
  368.     jz    kb_read_005        ;else
  369.     mov    bx,kb_q_head        ;    returns ZF=1
  370.     mov    ax,[bx]
  371.     call    kb_inc_ptr
  372.     mov    kb_q_head,bx
  373.     or    bh,0ffh          ;Reset ZF, operation successful
  374. kb_read_005 label  near
  375.     pop    bx
  376.     ret                ;Return to caller
  377. kb_read_q   endp
  378.     page
  379. ;****************************************************************************
  380. ;  KB_WRITE_Q - Add AX to keyboard queue.
  381. ;      If the keyboard queue is not full this routine adds the value in
  382. ;      AX to the tail of the queue.
  383. ;
  384. ;      Registers in:
  385. ;        AX   - Keyboard queue entry to be added
  386. ;      Registers out:
  387. ;        FF   - ZF=0 - Operation successful
  388. ;          ZF=1 - Operation unsuccessful
  389. ;             Keyboard queue was full
  390. ;      Registers preserved:
  391. ;        All except FF
  392. ;****************************************************************************
  393. kb_write_q  proc   near         ;If keyboard queue not full
  394.     push    bx            ;    adds AX to queue tail and
  395.     call    kb_is_q_full        ;    returns ZF=0
  396.     jz    kb_write_005        ;else
  397.     mov    bx,kb_q_tail        ;    returns ZF=1
  398.     mov    [bx],ax
  399.     call    kb_inc_ptr
  400.     mov    kb_q_tail,bx
  401.     or    bh,0ffh          ;Reset ZF, operation successful
  402. kb_write_005 label near
  403.     pop    bx
  404.     ret            ;Return to caller
  405. kb_write_q  endp
  406.  
  407. ;****************************************************************************
  408. ;****************************************************************************
  409. ;
  410. ;         IBM PC KEYBOARD INTERRUPT EMULATION ROUTINES
  411. ;
  412. ;
  413. ;  Each routine in this module is an interrupt service routine that
  414. ;  emulates the function performed by the corresponding service routine
  415. ;  in the IBM PC.  The service routines in this module support the IBM
  416. ;  PC keyboard functions.
  417. ;      ibm_io    - INT 016H, IBM keyboard I/O service routine
  418. ;      ibm_break - INT 01BH, IBM dummy user break service routine
  419. ;      ibm_int   - INT 043H, (IBM INT 009H) IBM keyboard interrupt
  420. ;****************************************************************************
  421. ;****************************************************************************
  422.  
  423. ;IBM keyboard flag byte kb_flag (kb_flag_msb) bit equates
  424. INS_MODE    equ    10000000B        ;Insert mode mask
  425. CAPS_MODE   equ    01000000B        ;Caps lock mode mask
  426. NUM_MODE    equ    00100000B        ;Numeric lock mode mask
  427. SCROLL_MODE equ    00010000B        ;Scroll lock mode mask
  428. EXT_SHIFT   equ    00001000B        ;Extended character key down mask
  429. CTRL_SHIFT  equ    00000100B        ;Control key down mask
  430. LEFT_SHIFT  equ    00000010B        ;Left shift key down mask
  431. RIGHT_SHIFT equ    00000001B        ;Right shift key down mask
  432.  
  433. ;IBM keyboard flag byte kb_flag_1 (kb_flag_lsb) bit equates
  434. INS_SHIFT   equ    10000000B        ;Insert key down mask
  435. CAPS_SHIFT  equ    01000000B        ;Caps lock key down mask
  436. NUM_SHIFT   equ    00100000B        ;Numeric lock key down mask
  437. SCROLL_SHIFT equ   00010000B        ;Scroll lock key down mask
  438. HOLD_MODE   equ    00001000B        ;Suspend mode mask
  439. ;    equ    00000100B        ;Unused
  440. ;    equ    00000010B        ;Unused
  441. ;    equ    00000001B        ;Unused
  442.  
  443. ;Interrupt type 016H keyboard I/O service function equates
  444. IBM_FCN_00  equ    000H         ;IBM function code 000
  445. IBM_FCN_01  equ    001H         ;IBM function code 001
  446. IBM_FCN_02  equ    002H         ;IBM function code 002
  447. HP_FCN_CODE equ    10000000B        ;HP function code mask
  448. HP_FCN_00   equ    080H         ;HP function code 000
  449. HP_FCN_01   equ    081H         ;HP function code 001
  450. HP_FCN_02   equ    082H         ;HP function code 002
  451. HP_FCN_03   equ    083H         ;HP function code 003
  452. HP_FCN_04   equ    084H         ;HP function code 004
  453. HP_FCN_05   equ    085H         ;HP function code 005
  454.  
  455. ;HP ITF keyboard key position equates.
  456. NUM_KEY     equ    088          ;HP-150 key 088
  457. SCROLL_KEY  equ    089          ;HP-150 key 089
  458. LEXT_KEY    equ    080          ;HP-150 key 080
  459. REXT_KEY    equ    082          ;HP-150 key 082
  460. CTRL_KEY    equ    048          ;HP-150 key 048
  461. CAPS_KEY    equ    047          ;HP-150 key 047
  462. LSHFT_KEY   equ    064          ;HP-150 key 064
  463. RSHFT_KEY   equ    075          ;HP-150 key 075
  464. INS_KEY     equ    029          ;HP-150 key 029
  465. BREAK_KEY   equ    001          ;HP-150 key 001
  466. STOP_KEY    equ    002          ;HP-150 key 002
  467. NPAD_0_KEY  equ    105          ;HP-150 key 105
  468. NPAD_1_KEY  equ    102          ;HP-150 key 102
  469. NPAD_2_KEY  equ    103          ;HP-150 key 103
  470. NPAD_3_KEY  equ    104          ;HP-150 key 104
  471. NPAD_4_KEY  equ    098          ;HP-150 key 098
  472. NPAD_5_KEY  equ    099          ;HP-150 key 099
  473. NPAD_6_KEY  equ    100          ;HP-150 key 100
  474. NPAD_7_KEY  equ    094          ;HP-150 key 094
  475. NPAD_8_KEY  equ    095          ;HP-150 key 095
  476. NPAD_9_KEY  equ    096          ;HP-150 key 096
  477.  
  478. ;These equates provide the proper displacement into a keycode mapping table
  479. ;entry depending on the current shift mode.
  480. BASE_INDEX  equ    000          ;Keycode table entry index
  481. SHIFT_INDEX equ    002          ;Keycode table entry index
  482. CTRL_INDEX  equ    004          ;Keycode table entry index
  483. EXTC_INDEX  equ    006          ;Keycode table entry index
  484.     page
  485.  
  486. ;The keyboard driver is installed by setting all necessary interrupt vectors
  487. ;to point to the proper driver routines.  Before the interrupt vectors are
  488. ;changed they are saved so that they may be restored to remove the keyboard
  489. ;driver and return the system to its normal keyboard state.
  490. ;These save areas are set up to store the original interrupt vectors.
  491. brk_save    label  dword        ;User break routine vector save
  492. brk_oset    dw     ?            ;    Offset
  493. brk_seg     dw     ?            ;    Segment
  494.  
  495. kbhw_save   label  dword        ;8041 interrupt vector save area
  496. kbhw_oset   dw     ?            ;    Offset
  497. kbhw_seg    dw     ?            ;    Segment
  498.  
  499. ;The keyboard interrupt service routine uses its own local stack.  The
  500. ;interrupt routine must be reentrant because of the PAUSE function.  Therefore,
  501. ;the interrupted routine's stack pointer is temporarily saved in the area
  502. ;defined here, the local stack is allocated from the stack space defined here,
  503. ;and the saved stack pointer is pushed onto the local stack.
  504. old_stack   label  dword        ;Interrupted routine's stack ptr
  505. old_sp      dw     0            ;    Saved SP
  506. old_ss      dw     0            ;    Saved SS
  507.  
  508. new_stack   label  word         ;kb_int local stack
  509.     dw    128 dup(?)        ;    128 word stack
  510. new_top     label  word         ;    Local stack top pointer
  511.  
  512. new_sp      dw     new_top        ;Top of stack pointer
  513. STACK_LEN   equ    (new_top-new_stack)/2    ;Allocated stack length
  514.  
  515. ;The keycode translation table is used to translate a key position number to
  516. ;a two byte keycode.  A pointer to the table is stored here so that an
  517. ;application may supply its own table to remap keys as needed.
  518. kb_kc_table label  dword        ;Keycode translation table pointer
  519. kb_kc_oset  dw     offset ibm_table    ;    Offset
  520. kb_kc_seg   dw     seg ibm_table    ;    Segment
  521.  
  522. ;The flag bytes reflect the current state of the shift keys and the state
  523. ;of toggle modes.  These flags correspond to the IBM PC keyboard flag bytes as
  524. ;follows:
  525. ;     kb_flag_msb ~ kb_flag
  526. ;     kb_flag_lsb ~ kb_flag_1
  527. kb_flag     label  word         ;Keyboard flags
  528. kb_flag_msb db     00000000B        ;    Keyboard flags MSB
  529. kb_flag_lsb db     00000000B        ;    Keyboard flags LSB
  530.  
  531. ;The touchscreen touch coordinates are reported in these bytes.  Note that
  532. ;touch reports are not buffered in any way - if the screen is being touched
  533. ;these bytes contain the coordinates of the touch.  These bytes are set to
  534. ;0FFFFH whenever the screen is not being touched.
  535. ts_row_col  label  word         ;Touchscreen touch coordinates
  536. ts_row      db     0FFH         ;    Touch row
  537. ts_col      db     0FFH         ;    Touch column
  538.  
  539. ;The 8041 reports two bytes for each screen touch - the first is the row
  540. ;coordinate and the second is the column coordinate.  The touch coordinates
  541. ;are not reported by the interrupt service routine until both have been read
  542. ;from the 8041.  Therefore, the row coordinate must be saved until the column
  543. ;coordinate is read.  The 8041 also reports a single byte when the touchscreen
  544. ;is released.
  545. ts_save     db     0FFH         ;Temp save area for row coordinate
  546.  
  547. ;The IBM PC keyboard alt-numeric pad special function is emulated.  The user
  548. ;can enter any character code (0-255) by pressing Extend char and typing the
  549. ;decimal value of a character code on the numeric pad keys.  Actually the
  550. ;range is (1-255) as in the IBM PC implementation.  This byte (ext_data)
  551. ;corresponds to the (alt_input) IBM PC keyboard byte.
  552. ext_data    db     000          ;Extend char data value
  553.  
  554. kb_shift    label  byte         ;Table of shift keys
  555.     db    INS_KEY          ;Any key entered in this table
  556.     db    CAPS_KEY         ;    will be trapped in the
  557.     db    NUM_KEY          ;    keyboard interrupt service
  558.     db    SCROLL_KEY        ;    routine as a shift key.  Note
  559.     db    LEXT_KEY         ;    that there is a one to one
  560.     db    REXT_KEY         ;    mapping from the entries in
  561.     db    CTRL_KEY         ;    this table to the entries in
  562.     db    LSHFT_KEY        ;    the following table kb_mask
  563.     db    RSHFT_KEY        ;    This table corresponds to the
  564. KB_SHIFT_LEN equ   $-kb_shift        ;    IBM PC keyboard table K6.
  565.  
  566. kb_mask     label  byte         ;Shift mask table
  567.     db    INS_SHIFT        ;The entries in this table are the
  568.     db    CAPS_SHIFT        ;    bit masks for the keyboard flag
  569.     db    NUM_SHIFT        ;    bytes corresponding to the
  570.     db    SCROLL_SHIFT        ;    shift keys in kb_shift.
  571.     db    EXT_SHIFT        ;    This table corresponds to the
  572.     db    EXT_SHIFT        ;    IBM PC keyboard table K7.
  573.     db    CTRL_SHIFT
  574.     db    LEFT_SHIFT
  575.     db    RIGHT_SHIFT
  576.  
  577. num_pad_keys label word         ;Numeric pad key table
  578.     db    NPAD_0_KEY        ;This is a table of the HP ITF
  579.     db    NPAD_1_KEY        ;    keyboard numeric pad keys.
  580.     db    NPAD_2_KEY        ;    Sequence is important here
  581.     db    NPAD_3_KEY        ;    because the displacement in
  582.     db    NPAD_4_KEY        ;    bytes from the beginning of the
  583.     db    NPAD_5_KEY        ;    table to any entry gives the
  584.     db    NPAD_6_KEY        ;    numeric value of the key.
  585.     db    NPAD_7_KEY        ;    This table corresponds to the
  586.     db    NPAD_8_KEY        ;    IBM PC keyboard table K30.
  587.     db    NPAD_9_KEY
  588. NUM_PAD_LEN equ    $-num_pad_keys
  589.  
  590.  
  591.     page
  592.  
  593. ;****************************************************************************
  594. ;  IBM_IO - Interrupt type 016H service routine.
  595. ;      Software interrupt - keyboard I/O service
  596. ;      This routine provides keyboard I/O service for an application
  597. ;      program.  Depending on the function code this routine can return
  598. ;      the current keyboard flags, queue status, next queue entry, or
  599. ;      touchscreen touch coordinates.
  600. ;
  601. ;      Registers in:
  602. ;        AH   - Function code:
  603. ;               000H - IBM function code 00
  604. ;                  Read the next key pressed and return the
  605. ;                  ascii code in AL and the extended code in
  606. ;                  AH
  607. ;               001H - IBM function code 01
  608. ;                  Return the keyboard queue status in ZF:
  609. ;                  ZF=1 - Keyboard queue is empty
  610. ;                  ZF=0 - Keyboard queue is not empty
  611. ;                     The first key in the queue is
  612. ;                     returned in AX and is left in the
  613. ;                     queue
  614. ;               002H - IBM function code 02
  615. ;                  Returns the current keyboard flags in AL
  616. ;               080H - HP function code 00
  617. ;                  Set keyboard keycode translation routine
  618. ;                  to use a translation table supplied by
  619. ;                  the application.
  620. ;                  ES:DX must contain pointer to table.
  621. ;               081H - HP function code 01
  622. ;                  Returns the touchscreen touch cooordinates
  623. ;                  in AX.  AH contains the row and AL contains
  624. ;                  the column coordinate.  The coordinates are
  625. ;                  equal to 0FFH if no touch is available
  626. ;               082H - HP function code 02
  627. ;                  Flushes all data from the keyboard queue.
  628. ;               083H - HP function code 03
  629. ;                  Starts this keyboard driver functioning by
  630. ;                  altering the proper interrupt vectors
  631. ;               084H - HP function code 04
  632. ;                  Stops this keyboard driver by restoring
  633. ;                  the interrupt vectors to the original
  634. ;                  firmware pointers
  635. ;               085H - HP function code 05
  636. ;                  Returns in ES:DX a pointer to the current
  637. ;                  keycode translation table
  638. ;      Registers out:
  639. ;        See each function code under Registers in.
  640. ;      Registers preserved:
  641. ;        All registers are preserved except AX and:
  642. ;        function code 001H - FF destroyed
  643. ;        function code 085H - ES, DX destroyed
  644. ;****************************************************************************
  645. ibm_io      label  far          ;External label for IBM keyboard
  646. kb_io    proc    far            ;    I/O interrupt service
  647.     sti                ;Enable external interrupts
  648.     push    bx            ;Save callers registers
  649.     push    ds
  650.     push    es
  651.     push    cs            ;Point ds to data segment
  652.     pop    ds
  653.     sub    bx,bx            ;Point es to segment 0
  654.     mov    es,bx
  655.     page
  656.     test    ah,HP_FCN_CODE        ;Jump if this is an HP function
  657.     jnz    kb_io_024
  658.     cmp    ah,IBM_FCN_00        ;IBM function 00 - Read keyboard
  659.     jz    kb_io_005        ;    queue
  660.     cmp    ah,IBM_FCN_01        ;IBM function 01 - Read keyboard
  661.     jz    kb_io_015        ;    queue status
  662.     cmp    ah,IBM_FCN_02        ;IBM function 02 - Read keyboard
  663.     jz    kb_io_020        ;    flags
  664.     jmp    kb_io_900        ;Invalid function code
  665.  
  666. kb_io_005   label  near         ;Read key from keyboard queue
  667.     cli
  668.     call    kb_read_q        ;If queue is empty then wait until
  669.     jnz    kb_io_010        ;    a key is pressed
  670.     sti                ;Enable external interrupts and
  671.     nop                ;    allow an interrupt to occur
  672.     jmp    kb_io_005        ;    and see if a key was pressed
  673. kb_io_010   label  near         ;Return the key in AX
  674.     jmp    kb_io_900        ;    AL-Ascii, AH-Extended code
  675.  
  676. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  677. ;  NOTE - This function call does not return through kb_io_900.  Be
  678. ;    careful with the stack and returns.
  679. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  680. kb_io_015   label  near         ;Read keyboard queue status
  681.     cli
  682.     mov    bx,kb_q_head        ;Read head queue entry without
  683.     mov    ax,[bx]          ;    removing it from queue
  684.     call    kb_is_q_empty        ;Set ZF to reflect queue status,
  685.     pop    es            ;    restore callers registers,
  686.     pop    ds            ;    throw away saved flags,
  687.     pop    bx            ;    enable external interrupts,
  688.     sti                ;    and return to caller
  689.     ret    2
  690.  
  691. kb_io_020   label  near         ;Read keyboard flags
  692.     mov    al,kb_flag_msb        ;Return keyboard flag byte in AL
  693.     jmp    kb_io_900
  694.     page
  695. kb_io_024   label  near         ;HP keyboard functions
  696.     cmp    ah,HP_FCN_00        ;HP function 00 - Set keycode
  697.     jz    kb_io_025        ;    translate table pointer
  698.     cmp    ah,HP_FCN_01        ;HP function 01 - Read touchscreen
  699.     jz    kb_io_030        ;    touch coordinates
  700.     cmp    ah,HP_FCN_02        ;HP function 02 - Flush keyboard
  701.     jz    kb_io_035        ;    queue
  702.     cmp    ah,HP_FCN_03        ;HP function 03 - Start keyboard
  703.     jz    kb_io_040        ;    driver
  704.     cmp    ah,HP_FCN_04        ;HP function 04 - Stop keyboard
  705.     jz    kb_io_045        ;    driver
  706.     cmp    ah,HP_FCN_05        ;HP function 05 - Read keycode
  707.     jz    kb_io_050        ;    translate table pointer
  708.     jmp    kb_io_900
  709.  
  710. kb_io_025   label  near         ;Set keycode translate table ptr
  711.     cli                ;Store user keycode translate table
  712.     mov    kb_kc_oset,dx        ;    pointer for interrupt service
  713.     mov    kb_kc_seg,es        ;    routine
  714.     jmp    kb_io_900
  715.  
  716. kb_io_030   label  near         ;Read touch coordinates
  717.     mov    ax,ts_row_col        ;    Get touch coordinates in AX
  718.     jmp    kb_io_900        ;    AH - row, AL - column
  719.  
  720. kb_io_035   label  near         ;Flush keyboard queue
  721.     cli                ;Disable external interrupts
  722.     call    kb_reset_q        ;Flush queue
  723.     jmp    kb_io_900
  724.  
  725. kb_io_040   label  near         ;Start keyboard driver
  726.     cli
  727.     mov    ax,es:break_oset ;Save current user break vector
  728.     mov    brk_oset,ax
  729.     mov    ax,es:break_seg
  730.     mov    brk_seg,ax
  731.     mov    ax,es:kb_int_oset    ;Save current 8041 interrupt vector
  732.     mov    kbhw_oset,ax
  733.     mov    ax,es:kb_int_seg
  734.     mov    kbhw_seg,ax
  735.     mov    ax,offset ibm_break    ;Install new user break vector
  736.     mov    es:break_oset,ax
  737.     mov    es:break_seg,cs
  738.     mov    ax,offset ibm_int    ;Install new 8041 interrupt vector
  739.     mov    es:kb_int_oset,ax
  740.     mov    es:kb_int_seg,cs
  741.     jmp    kb_io_900
  742.  
  743. kb_io_045   label  near         ;Stop keyboard driver
  744.     cli
  745.     mov    ax,brk_oset        ;Restore user break vector
  746.     mov    es:break_oset,ax
  747.     mov    ax,brk_seg
  748.     mov    es:break_seg,ax
  749.     mov    ax,kbhw_oset        ;Restore 8041 interrupt vector
  750.     mov    es:kb_int_oset,ax
  751.     mov    ax,kbhw_seg
  752.     mov    es:kb_int_seg,ax
  753.     jmp    kb_io_900
  754.  
  755. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  756. ;  NOTE - This function call does not return through kb_io_900.  Be
  757. ;    careful with the stack and returns.
  758. ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  759. kb_io_050   label  near         ;Read keycode translate table ptr
  760.     cli                ;Load pointer to current keycode
  761.     les    dx,kb_kc_table        ;    translate table
  762.     pop    ds            ;Throw away callers es register
  763.     pop    ds            ;Restore remaining registers
  764.     pop    bx
  765.     iret                ;Return to caller
  766.  
  767. kb_io_900   label  near
  768.     pop    es            ;Restore callers registers
  769.     pop    ds            ;    and return to caller
  770.     pop    bx
  771.     iret
  772. kb_io    endp
  773.     page
  774. ;****************************************************************************
  775. ;  IBM_BREAK - Interrupt type 01BH service routine.
  776. ;         Software interrupt - user break routine
  777. ;      This is a dummy user break routine.  At initialization the
  778. ;      user break interrupt vector is set to this routine.
  779. ;
  780. ;      Registers in:
  781. ;        None.
  782. ;      Registers out:
  783. ;        None.
  784. ;      Registers preserved:
  785. ;        All.
  786. ;****************************************************************************
  787. ibm_break   label  far          ;External label for dummy user
  788. kb_break    proc   far          ;    break routine
  789.     iret                ;Return to caller
  790. kb_break    endp
  791.     page
  792. ;****************************************************************************
  793. ;  IBM_INT - Interrupt type 043H service routine.
  794. ;        (IBM interrupt type 009H service routine)
  795. ;        Hardware interrupt - 8041 interrupt
  796. ;      This routine receives control whenever the 8041 signals an
  797. ;      interrupt through the 8259 interrupt controller to the 8088.
  798. ;      This service routine emulates all of the functions performed by
  799. ;      the IBM PC keyboard interrupt (type 09).  The data is read from
  800. ;      the 8041, processed as needed, translated to ascii and extended
  801. ;      codes, and placed in the keyboard queue.  Touchscreen data is
  802. ;      simply saved in a memory word.
  803. ;
  804. ;      1) Do if data byte from keyboard
  805. ;     1.1) Translate physical key address to key position
  806. ;     1.2) Do if not a keyboard shift key
  807. ;          1.2.1) Do if key pressed (not released)
  808. ;             1.2.1.1) Do if hold mode active
  809. ;                  1.2.1.1.1) Reset hold mode
  810. ;                  1.2.1.1.2) End of processing
  811. ;             1.2.1.2) Do if base mode
  812. ;                  1.2.1.2.1) Do if stop key
  813. ;                     1.2.1.2.1.1) Wait for another
  814. ;                              key press
  815. ;                     1.2.1.2.1.2) End of processing
  816. ;                  1.2.1.2.2) Do if break key
  817. ;                     1.2.1.2.2.1) Reset keyboard q
  818. ;                     1.2.1.2.2.2) Call user break
  819. ;                              routine
  820. ;                  1.2.1.2.3) Translate key to ascii and
  821. ;                     extended codes and put in queue
  822. ;             1.2.1.3) Do if in extended char mode
  823. ;                  1.2.1.3.1) Do if a numeric pad key
  824. ;                     1.2.1.3.1.1) Add key value to
  825. ;                              input data value
  826. ;                     1.2.1.3.1.1) End of processing
  827. ;                  1.2.1.3.2) Translate key to ascii and
  828. ;                     extended codes and put in queue
  829. ;             1.2.1.4) Do if in control mode
  830. ;                  1.2.1.4.1) Translate key to ascii and
  831. ;                     extended codes and put in queue
  832. ;             1.2.1.5) Do if in shift mode
  833. ;                  1.2.1.5.1) Translate key to ascii and
  834. ;                     extended codes and put in queue
  835.     page
  836. ;     1.3) Do if a keyboard shift key
  837. ;          1.3.1) Do if the key was pressed (not released)
  838. ;             1.3.1.1) Do if not a toggle shift key
  839. ;                  1.3.1.1.1) Set key pressed flag
  840. ;             1.3.1.2) Do if a toggle shift key
  841. ;                  1.3.1.2.1) Do if in control mode
  842. ;                     1.3.1.2.1.1) Translate key to
  843. ;                              ascii and extended
  844. ;                              codes and put in q
  845. ;                  1.3.1.2.2) Do if key not already pressed
  846. ;                     1.3.1.2.2.1) Set key pressed flg**
  847. ;                     1.3.1.2.2.2) Toggle mode flag
  848. ;          1.3.2) Do if the key was released
  849. ;             1.3.2.1) Do if not a toggle shift key
  850. ;                  1.3.2.1) Reset key pressed flag
  851. ;                  1.3.2.2) Do if shift key is ext char
  852. ;                       1.3.2.2.1) Do if input value
  853. ;                          is not zero
  854. ;                          1.3.2.2.1.1) Put input
  855. ;                             value in keyboard q
  856. ;             1.3.2.2) Do if a toggle shift key
  857. ;                  1.3.2.1) Reset key pressed flag
  858. ;      2) Do if data from touchscreen
  859. ;     2.1) Do if row report
  860. ;          2.1.1) Save row coordinate
  861. ;     2.2) Do if column report
  862. ;          2.2.1) Correct column coordinate (multiply by two)
  863. ;          2.2.2) Put row and column in touchscreen data word
  864. ;     2.3) Do if touchscreen release report
  865. ;          2.3.1) Set touchscreen data word to 0FFFFH
  866. ;
  867. ;      Registers in:
  868. ;        None.
  869. ;      Registers out:
  870. ;        None.
  871. ;      Registers preserved:
  872. ;        All.
  873. ;****************************************************************************
  874.     page
  875. ibm_int     label  far          ;External label for IBM keyboard
  876. kb_int      proc   far          ;    interrupt service routine
  877.     push    ax            ;Save only what we absolutely must
  878.     push    ds            ;    on the current stack
  879.     push    cs            ;Point ds to data segment
  880.     pop    ds
  881.     mov    old_ss,ss        ;Save current stack pointer
  882.     mov    old_sp,sp
  883.     mov    ax,cs
  884.     mov    ss,ax            ;Switch to local stack
  885.     mov    sp,new_sp
  886.     sub    new_sp,STACK_LEN     ;Record stack allocation
  887.     push    old_ss            ;Save everything we need to that
  888.     push    old_sp            ;    wasn't saved before
  889.     push    bx
  890.     push    cx
  891.     push    di
  892.     push    es
  893.     sti                ;Enable higher-priority interrupts
  894.     in    al,KB_STAT        ;Read 8041 status byte
  895.     test    al,OBF_MASK        ;If no data ready from 8041 then
  896.     jnz    kb_int_005        ;    don't do anything
  897.     jmp    kb_int_900
  898.  
  899. kb_int_005  label  near
  900.     cld                ;Set string instrs to increment
  901.     mov    ah,al            ;Save 8041 status byte
  902.     in    al,KB_DATA        ;Read data byte from 8041
  903.     push    ax
  904.     mov    ah,ACK_CMND        ;Acknowledge 8041 interrupt
  905.     call    kb_cmnd_out
  906.     pop    ax
  907.     test    ah,TS_MASK        ;If the data byte came from the
  908.     jz    kb_int_010        ;    touchscreen then go process it
  909.     jmp    kb_int_200
  910.     page
  911. ;----------------------------------------------------------------------------
  912. ;  8041 data byte from keyboard
  913. ;----------------------------------------------------------------------------
  914. kb_int_010  label  near         ;Data byte from keyboard
  915.     push    ds            ;Point es to data segment
  916.     pop    es
  917.     mov    ah,al            ;Save keyboard data byte
  918.     and    al,not KEY_RELEASE    ;Mask off key released bit
  919.     mov    bx,offset key_number    ;Translate physical key address to
  920.     xlat                ;    key position number
  921.     mov    di,offset kb_shift    ;Use the table of keyboard shift
  922.     mov    cx,KB_SHIFT_LEN      ;    keys to see if this key is a
  923.     repne  scasb            ;    shift key
  924.     jne    kb_int_015        ;If it is a shift key then go
  925.     jmp    kb_int_100        ;    process it
  926.  
  927. kb_int_015  label  near         ;Not a shift key, AH-pa AL-key no
  928.     test    ah,KEY_RELEASE        ;If the key was released then
  929.     jz    kb_int_020        ;    ignore it
  930.     jmp    kb_int_900
  931. kb_int_020  label  near
  932.     test    kb_flag_lsb,HOLD_MODE    ;If we are in hold mode then
  933.     jz    kb_int_030        ;    end hold mode and ignore key
  934.     and    kb_flag_lsb,not HOLD_MODE
  935.     jmp    kb_int_900
  936.  
  937. kb_int_030  label  near         ;Process non-shift key
  938.     test    kb_flag_msb,EXT_SHIFT    ;If in extended character mode
  939.     jnz    kb_int_040        ;    go to ext char routine
  940.     test    kb_flag_msb,CTRL_SHIFT    ;If in control mode
  941.     jnz    kb_int_050        ;    go to control routine
  942.     test    kb_flag_msb,LEFT_SHIFT or RIGHT_SHIFT ;If in shift mode
  943.     jnz    kb_int_060        ;    go to shift routine
  944.     jmp    kb_int_035        ;Go to base mode routine
  945.  
  946. kb_int_035  label  near         ;Process non-shift key, base mode
  947.     cmp    al,STOP_KEY        ;If the key is the stop key
  948.     jnz    kb_int_038        ;    then suspend processing until
  949.     or    kb_flag_lsb,HOLD_MODE    ;    another key is pressed
  950.     mov    al,EOI_CMND        ;    (This is the CTRL-NumLock
  951.     out    IC_CMND,al        ;     function on the IBM keyboard)
  952. kb_int_037  label  near
  953.     test    kb_flag_lsb,HOLD_MODE
  954.     jnz    kb_int_037
  955.     jmp    kb_int_910
  956. kb_int_038  label  near         ;else  (not stop key)
  957.     cmp    al,BREAK_KEY        ;    If the key is the break key
  958.     jnz    kb_int_039        ;       empty keyboard buffer
  959.     call    kb_reset_q        ;       call user break routine
  960.     int    BREAK_TYPE        ;       put zero keycode in queue
  961.     mov    ax,00000H        ;       (IBM is CTRL-ScrollLock)
  962.     jmp    kb_int_805        ;    endif
  963. kb_int_039  label  near
  964.     mov    cx,BASE_INDEX        ;    Put keycode in queue
  965.     jmp    kb_int_800        ;endif
  966.  
  967. kb_int_040  label  near         ;Process non-shift key, extc mode
  968.     mov    di,offset num_pad_keys
  969.     mov    cx,NUM_PAD_LEN
  970.     repne  scasb            ;If the key is a numeric pad key
  971.     jne    kb_int_045        ;    then add the value to the
  972.     sub    di,offset num_pad_keys+1 ;    current input value
  973.     mov    al,ext_data
  974.     mov    ah,10
  975.     mul    ah
  976.     add    ax,di
  977.     mov    ext_data,al
  978.     jmp    kb_int_900
  979. kb_int_045  label  near         ;else  (not numeric pad key)
  980.     mov    ext_data,0        ;    clear input value
  981.     mov    cx,EXTC_INDEX        ;    put keycode in queue
  982.     jmp    kb_int_800        ;endif
  983.  
  984. kb_int_050  label  near         ;Process non-shift key, ctrl mode
  985.     mov    cx,CTRL_INDEX        ;Put keycode in queue
  986.     jmp    kb_int_800
  987.  
  988. kb_int_060  label  near         ;Process non-shift key, shift mode
  989.     mov    cx,SHIFT_INDEX        ;Put keycode in queue
  990.     jmp    kb_int_800
  991.  
  992. ;Keyboard shift key, AH-physical addr  AH-key number
  993. ;         DI-pointer to shift key table entry
  994. kb_int_100  label  near
  995.     sub    di,offset kb_shift+1    ;Load shift key flag byte mask
  996.     mov    bl,kb_mask[di]        ;    in bl
  997.     test    ah,KEY_RELEASE        ;If the shift key was pressed
  998.     jnz    kb_int_120
  999.     cmp    bl,SCROLL_SHIFT      ;    If not a toggle shift key
  1000.     jae    kb_int_105
  1001.     or    kb_flag_msb,bl        ;       Set key pressed flag
  1002.     jmp    kb_int_900
  1003. kb_int_105  label  near         ;    else  (toggle shift key)
  1004.     test    kb_flag_msb,CTRL_SHIFT    ;       If in control mode
  1005.     jz    kb_int_110        ;      go to non-shift key proc
  1006.     jmp    kb_int_015        ;       endif
  1007. kb_int_110  label  near
  1008.     test    bl,kb_flag_lsb        ;       If key already pressed
  1009.     jz    kb_int_115        ;      ignore it
  1010.     jmp    kb_int_900        ;       endif
  1011. kb_int_115  label  near
  1012.     or    kb_flag_lsb,bl        ;       Set key pressed flag
  1013.     xor    kb_flag_msb,bl        ;       Toggle the mode flag
  1014.     cmp    al,INS_KEY        ;       If key is insert key
  1015.     jnz    kb_int_117        ;      put keycode in queue
  1016.     jmp    kb_int_030        ;       endif
  1017. kb_int_117  label  near
  1018.     jmp    kb_int_900        ;    endif
  1019.  
  1020. kb_int_120  label  near         ;else  (shift key released)
  1021.     cmp    bl,SCROLL_SHIFT      ;    If not a toggle shift key
  1022.     jae    kb_int_135
  1023.     not    bl            ;       Reset key pressed flag
  1024.     and    kb_flag_msb,bl
  1025.     cmp    al,LEXT_KEY        ;       If an ext char key was
  1026.     jz    kb_int_125        ;      released
  1027.     cmp    al,REXT_KEY
  1028.     jz    kb_int_125
  1029.     jmp    kb_int_900
  1030. kb_int_125  label  near
  1031.     mov    al,ext_data        ;      If the input value is not
  1032.     or    al,al            ;         zero
  1033.     jnz    kb_int_130
  1034.     jmp    kb_int_900        ;         zero save area
  1035. kb_int_130  label  near         ;         put data value in
  1036.     mov    ext_data,0        ;        keyboard queue
  1037.     sub    ah,ah            ;      endif
  1038.     jmp    kb_int_805        ;    endif
  1039.  
  1040. kb_int_135  label  near         ;    else  (toggle shift key)
  1041.     not    bl            ;       Reset key pressed flag
  1042.     and    kb_flag_lsb,bl        ;    endif
  1043.     jmp    kb_int_900        ;    endif
  1044.     page
  1045. ;----------------------------------------------------------------------------
  1046. ;  8041 data byte from touchscreen
  1047. ;----------------------------------------------------------------------------
  1048. kb_int_200  label  near         ;Touchscreen input
  1049.     and    ah,TS_MASK        ;Isolate touchscreen flags
  1050.     cmp    ah,ROW_MASK        ;If touch row report then
  1051.     jz    kb_int_205        ;    go process it
  1052.     cmp    ah,COL_MASK        ;If touch column report then
  1053.     jz    kb_int_210        ;    go process it
  1054.     cmp    ah,REL_MASK        ;If touchscreen release then
  1055.     jz    kb_int_215        ;    go process it
  1056.     jmp    kb_int_900
  1057.  
  1058. kb_int_205  label  near         ;Touchscreen row report
  1059.     mov    ts_save,al        ;Save touch row coordinate
  1060.     jmp    kb_int_900
  1061.  
  1062. ;The 8041 reports touch column coordinates in the range 0-40.  Therefore,
  1063. ;the column coordinate must be multiplied by two to be in the range 0-80.
  1064. ;NOTE - this means that a touch column coordinate will never be odd.
  1065. kb_int_210  label  near         ;Touchscreen column report
  1066.     mov    ah,0FFH          ;Load row coordinate
  1067.     xchg    ts_save,ah
  1068.     sal    al,1            ;Correct column coordinate
  1069.     mov    ts_row_col,ax        ;Store touch coordinates
  1070.     jmp    kb_int_900
  1071.  
  1072. kb_int_215  label  near         ;Touchscreen released
  1073.     mov    ax,0FFFFH        ;Clear touch coordinates
  1074.     xchg    ts_row_col,ax
  1075.     jmp    kb_int_900
  1076.     page
  1077. ;----------------------------------------------------------------------------
  1078. ;  Translate key number to ascii and extended code depending on shift mode
  1079. ;      AL-HP ITF key position number, CX-Shift mode index value
  1080. ;----------------------------------------------------------------------------
  1081. kb_int_800  label  near
  1082.     les    bx,kb_kc_table        ;Load pointer to keycode translate
  1083.     add    bx,cx            ;    table and index into table
  1084.     sub    ah,ah            ;    using key number and shift
  1085.     mov    cl,3            ;    mode.
  1086.     sal    ax,cl
  1087.     add    bx,ax            ;Load keycode table entry giving
  1088.     mov    ax,es:[bx]        ;    AH-Extended code, AL-Ascii code
  1089.     cmp    ah,0FFH          ;Ignore any non-mapped keys
  1090.     jz    kb_int_900
  1091.     cmp    al,0FFH
  1092.     jz    kb_int_900
  1093.  
  1094. ;----------------------------------------------------------------------------
  1095. ;  Put keycode (ascii code plus extended code) in keyboard queue
  1096. ;      AH-extended code, AL-ascii code
  1097. ;----------------------------------------------------------------------------
  1098. kb_int_805  label  near
  1099.     test    kb_flag_msb,CAPS_MODE    ;If in caps lock mode then
  1100.     jz    kb_int_815
  1101.     test    kb_flag_msb,LEFT_SHIFT or RIGHT_SHIFT
  1102.     jnz    kb_int_810        ;    If not in shift mode then
  1103.     cmp    al,'a'
  1104.     jb    kb_int_815
  1105.     cmp    al,'z'            ;       If lowercase ascii alpha
  1106.     ja    kb_int_815        ;      convert to uppercase
  1107.     and    al,11011111B        ;       endif
  1108.     jmp    kb_int_815        ;
  1109. kb_int_810  label  near         ;    else
  1110.     cmp    al,'A'            ;       If uppercase ascii alpha
  1111.     jb    kb_int_815        ;      convert to lowercase
  1112.     cmp    al,'Z'            ;       endif
  1113.     ja    kb_int_815        ;    endif
  1114.     or    al,00100000B        ;endif
  1115.  
  1116. kb_int_815  label  near
  1117.     call    kb_write_q        ;Add keycode to keyboard queue
  1118.     jnz    kb_int_900        ;Make noise if queue is full
  1119.     mov    ah,TONE_0_CMND
  1120.     call    kb_cmnd_out
  1121.     jmp    kb_int_900
  1122.     page
  1123. kb_int_900  label  near         ;End of keyboard interrupt service
  1124.     cli                ;Disable external interrupts
  1125.     mov    al,EOI_CMND        ;Send End of Interrupt command to
  1126.     out    IC_CMND,al        ;    8259 interrupt controller
  1127. kb_int_910  label  near         ;End of keyboard intr, no EOI
  1128.     cli                ;Disable external interrupts
  1129.     pop    es            ;Restore saved values
  1130.     pop    di
  1131.     pop    cx
  1132.     pop    bx
  1133.     pop    old_sp
  1134.     pop    old_ss
  1135.     mov    ss,old_ss        ;Restore interrupted routines's
  1136.     mov    sp,old_sp        ;    stack pointer
  1137.     add    new_sp,STACK_LEN ;Release allocated stack space
  1138.     sti
  1139.     pop    ds            ;Restore saved registers
  1140.     pop    ax
  1141.     iret                ;Return from interrupt
  1142. kb_int      endp
  1143.  
  1144.  
  1145. ;****************************************************************************
  1146. ;****************************************************************************
  1147. ;
  1148. ;              KEYBOARD DRIVER TRANSLATE TABLES
  1149. ;
  1150. ;
  1151. ;  This module contains the translate tables used by the keyboard driver.
  1152. ;      key_number - Key physical address to key number translate table
  1153. ;      ibm_table  - Key number to IBM PC keycode translate table
  1154. ;****************************************************************************
  1155. ;****************************************************************************
  1156.  
  1157.  
  1158. ;****************************************************************************
  1159. ;  KEY_NUMBER - Key physical address to key number translate table
  1160. ;      This table translates the physical address for a key that is
  1161. ;      reported by the 8041 to the key's position number on the ITF
  1162. ;      keyboard.
  1163. ;
  1164. ;      The physical key address reported by the 8041 is a 7-bit value -
  1165. ;      the eighth bit is used to indicate whether the key went up or
  1166. ;      down.  Therefore, there are only 128 possible entries in this
  1167. ;      table.  The physical key address is used to index this table and
  1168. ;      the resulting value is the corresponding ITF key number.
  1169. ;      A value of zero indicates no key corresponds to the physical addr.
  1170. ;****************************************************************************
  1171. key_number  label  word
  1172. ;          ITF keyboard key position      Physical
  1173. ;            (000 = No key)    address
  1174.     db    000,000,000,000,000,000,000,000   ;000-007
  1175.     db    007,014,013,012,011,010,009,008   ;008-00F
  1176.     db    023,030,029,028,027,026,025,024   ;010-017
  1177.     db    039,046,045,044,043,042,041,040   ;018-01F
  1178.     db    055,062,061,060,059,058,057,056   ;020-027
  1179.     db    071,078,077,076,016,074,073,072   ;028-02F
  1180.     db    000,085,084,083,000,082,080,081   ;030-037
  1181.     db    006,053,002,048,015,003,004,005   ;038-03F
  1182.     db    022,064,075,047,018,019,020,021   ;040-047
  1183.     db    038,031,032,033,034,035,036,037   ;048-04F
  1184.     db    054,017,000,049,050,051,052,001   ;050-057
  1185.     db    101,097,100,096,099,095,098,094   ;058-05F
  1186.     db    107,093,104,092,103,091,102,090   ;060-067
  1187.     db    000,089,106,088,000,087,105,086   ;068-06F
  1188.     db    070,063,079,065,066,067,068,069   ;070-077
  1189.     db    000,000,000,000,000,000,000,000   ;078-07F
  1190.     page
  1191. ;****************************************************************************
  1192. ;  IBM_TABLE - Key number to IBM PC keycode translate table
  1193. ;      This table translates a key number and shift mode to an IBM PC
  1194. ;      keycode.
  1195. ;
  1196. ;      The key number is multiplied by six and the result is used to
  1197. ;      index the table.  Each table entry is made up of four two-byte
  1198. ;      keycodes corresponding to base, shift, ctrl, and extc shift modes
  1199. ;      respectively.  The shift mode is used to index the table entry and
  1200. ;      the resulting two-byte value is the IBM PC keycode.
  1201. ;
  1202. ;      The IBM PC keycode is a one word value made up of two single byte
  1203. ;      codes.  The MSB contains the IBM extended character code and the
  1204. ;      LSB contains the IBM ascii code for the key.
  1205. ;****************************************************************************
  1206. ibm_table   label  word
  1207. ;                    Ext     HP
  1208. ;        Base    Shift    Ctrl    Char    Key #
  1209.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;000 - dummy key entry
  1210.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;001
  1211.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;002
  1212.     dw    03B00H, 05400H, 05E00H, 06800H    ;003
  1213.     dw    03C00H, 05500H, 05F00H, 06900H    ;004
  1214.     dw    03D00H, 05600H, 06000H, 06A00H    ;005
  1215.     dw    03E00H, 05700H, 06100H, 06B00H    ;006
  1216.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;007
  1217.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;008
  1218.     dw    03F00H, 05800H, 06200H, 06C00H    ;009
  1219.     dw    04000H, 05900H, 06300H, 06D00H    ;010
  1220.     dw    04100H, 05A00H, 06400H, 06E00H    ;011
  1221.     dw    04200H, 05B00H, 06500H, 06F00H    ;012
  1222.     dw    07500H, 07500H, 0FFFFH, 0FFFFH    ;013
  1223.     dw    07700H, 07700H, 0FFFFH, 0FFFFH    ;014
  1224.     dw    02960H, 0297EH, 0FFFFH, 0FFFFH    ;015
  1225.     dw    00231H, 00221H, 0FFFFH, 07800H    ;016
  1226.     dw    00332H, 00340H, 00000H, 07900H    ;017
  1227.     dw    00433H, 00423H, 0FFFFH, 07A00H    ;018
  1228.     dw    00534H, 00524H, 0FFFFH, 07B00H    ;019
  1229.     dw    00635H, 00625H, 0FFFFH, 07C00H    ;020
  1230.     dw    00736H, 0075EH, 0071EH, 07D00H    ;021
  1231.     dw    00837H, 00826H, 0FFFFH, 07E00H    ;022
  1232.     dw    00938H, 0092AH, 0FFFFH, 07F00H    ;023
  1233.     dw    00A39H, 00A28H, 0FFFFH, 08000H    ;024
  1234.     dw    00B30H, 00B29H, 0FFFFH, 08100H    ;025
  1235.     dw    00C2DH, 00C5FH, 00C1FH, 08200H    ;026
  1236.     dw    00D3DH, 00D2BH, 0FFFFH, 08300H    ;027
  1237.     dw    00E08H, 00E08H, 00E7FH, 0FFFFH    ;028
  1238.     dw    05200H, 05200H, 0FFFFH, 0FFFFH    ;029
  1239.     dw    05300H, 05300H, 0FFFFH, 0FFFFH    ;030
  1240.     dw    00F09H, 00F00H, 0FFFFH, 0FFFFH    ;031
  1241.     dw    01071H, 01051H, 01011H, 01000H    ;032
  1242.     dw    01177H, 01157H, 01117H, 01100H    ;033
  1243.     dw    01265H, 01245H, 01205H, 01200H    ;034
  1244.     dw    01372H, 01352H, 01312H, 01300H    ;035
  1245.     dw    01474H, 01454H, 01414H, 01400H    ;036
  1246.     dw    01579H, 01559H, 01519H, 01500H    ;037
  1247.     dw    01675H, 01655H, 01615H, 01600H    ;038
  1248.     dw    01769H, 01749H, 01709H, 01700H    ;039
  1249.     dw    0186FH, 0184FH, 0180FH, 01800H    ;040
  1250.     dw    01970H, 01950H, 01910H, 01900H    ;041
  1251.     dw    01A5BH, 01A7BH, 01A1BH, 0FFFFH    ;042
  1252.     dw    01B5DH, 01B7DH, 01B1DH, 0FFFFH    ;043
  1253.     dw    02B5CH, 02B7CH, 02B1CH, 0FFFFH    ;044
  1254.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;045
  1255.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;046
  1256.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;047
  1257.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;048
  1258.     dw    01E61H, 01E41H, 01E01H, 01E00H    ;049
  1259.     dw    01F73H, 01F53H, 01F13H, 01F00H    ;050
  1260.     dw    02064H, 02044H, 02004H, 02000H    ;051
  1261.     dw    02166H, 02146H, 02106H, 02100H    ;052
  1262.     dw    02267H, 02247H, 02207H, 02200H    ;053
  1263.     dw    02368H, 02348H, 02308H, 02300H    ;054
  1264.     dw    0246AH, 0244AH, 0240AH, 02400H    ;055
  1265.     dw    0256BH, 0254BH, 0250BH, 02500H    ;056
  1266.     dw    0266CH, 0264CH, 0260CH, 02600H    ;057
  1267.     dw    0273BH, 0273AH, 0FFFFH, 0FFFFH    ;058
  1268.     dw    02827H, 02822H, 0FFFFH, 0FFFFH    ;059
  1269.     dw    01C0DH, 01C0DH, 01C0AH, 0FFFFH    ;060
  1270.     dw    04700H, 04700H, 0FFFFH, 0FFFFH    ;061
  1271.     dw    04900H, 04900H, 08400H, 0FFFFH    ;062
  1272.     dw    0011BH, 0011BH, 0011BH, 0FFFFH    ;063
  1273.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;064
  1274.     dw    02C7AH, 02C5AH, 02C1AH, 02C00H    ;065
  1275.     dw    02D78H, 02D58H, 02D18H, 02D00H    ;066
  1276.     dw    02E63H, 02E43H, 02E03H, 02E00H    ;067
  1277.     dw    02F76H, 02F56H, 02F16H, 02F00H    ;068
  1278.     dw    03062H, 03042H, 03002H, 03000H    ;069
  1279.     dw    0316EH, 0314EH, 0310EH, 03100H    ;070
  1280.     dw    0326DH, 0324DH, 0320DH, 03200H    ;071
  1281.     dw    0332CH, 0333CH, 0FFFFH, 0FFFFH    ;072
  1282.     dw    0342EH, 0343EH, 0FFFFH, 0FFFFH    ;073
  1283.     dw    0352FH, 0353FH, 0FFFFH, 0FFFFH    ;074
  1284.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;075
  1285.     dw    04F00H, 04F00H, 0FFFFH, 0FFFFH    ;076
  1286.     dw    04800H, 04800H, 0FFFFH, 0FFFFH    ;077
  1287.     dw    05100H, 05100H, 07600H, 0FFFFH    ;078
  1288.     dw    0FFFFH, 0FFFFH, 07200H, 0FFFFH    ;079
  1289.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;080
  1290.     dw    03920H, 03920H, 03920H, 03920H    ;081
  1291.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;082
  1292.     dw    04B00H, 04B00H, 07300H, 0FFFFH    ;083
  1293.     dw    05000H, 05000H, 0FFFFH, 0FFFFH    ;084
  1294.     dw    04D00H, 04D00H, 07400H, 0FFFFH    ;085
  1295.     dw    04300H, 05C00H, 06600H, 07000H    ;086
  1296.     dw    04400H, 05D00H, 06700H, 07100H    ;087
  1297.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;088
  1298.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;089
  1299.     dw    0372AH, 0372AH, 0FFFFH, 0FFFFH    ;090
  1300.     dw    0352FH, 0352FH, 0FFFFH, 0FFFFH    ;091
  1301.     dw    04E2BH, 04E2BH, 0FFFFH, 0FFFFH    ;092
  1302.     dw    04A2DH, 04A2DH, 0FFFFH, 0FFFFH    ;093
  1303.     dw    04737H, 04737H, 0FFFFH, 0FFFFH    ;094
  1304.     dw    04838H, 04838H, 0FFFFH, 0FFFFH    ;095
  1305.     dw    04939H, 04939H, 0FFFFH, 0FFFFH    ;096
  1306.     dw    0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH    ;097
  1307.     dw    04B34H, 04B34H, 0FFFFH, 0FFFFH    ;098
  1308.     dw    04C35H, 04C35H, 0FFFFH, 0FFFFH    ;099
  1309.     dw    04D36H, 04D36H, 0FFFFH, 0FFFFH    ;100
  1310.     dw    0332CH, 0332CH, 0FFFFH, 0FFFFH    ;101
  1311.     dw    04F31H, 04F31H, 0FFFFH, 0FFFFH    ;102
  1312.     dw    05032H, 05032H, 0FFFFH, 0FFFFH    ;103
  1313.     dw    05133H, 05133H, 0FFFFH, 0FFFFH    ;104
  1314.     dw    05230H, 05230H, 0FFFFH, 0FFFFH    ;105
  1315.     dw    0342EH, 0342EH, 0FFFFH, 0FFFFH    ;106
  1316.     dw    00F09H, 00F00H, 0FFFFH, 0FFFFH    ;107
  1317.  
  1318. pccode      ends
  1319.  
  1320.     end
  1321.